home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 October / EnigmA AMIGA RUN 31 (1998)(G.R. Edizioni)(IT)[!][issue 1998-10].iso / linux / ppmtoagafb-0.7 / encodeham8.c < prev    next >
C/C++ Source or Header  |  1998-09-22  |  4KB  |  155 lines

  1. /* HAM8 encoding, based on the jpegAGA HAM8 encoding
  2.  * Originally by Günther Röhrich
  3.  * Converted to C by Chris Lawrence <quango@themall.net>
  4.  * 
  5.  *  (©) Copyright 1996-97 by Chris Lawrence
  6.  *
  7.  *  This file is subject to the terms and conditions of the GNU General Public
  8.  *  License.  See the file COPYING in the main directory of the Linux
  9.  *  distribution for more details.
  10.  *
  11.  * To do: translate this into human-readable C
  12.  *        (as opposed to assembleresque C).
  13.  *        gcc might then be able to optimize it decently.
  14.  */
  15.  
  16. #include <sys/types.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "ppm.h"
  20.  
  21. extern u_char ColorTable[64 * 3], *ColorCache;
  22. extern u_short Mult_Table[256 * 2];
  23.  
  24. static u_short compute_error(u_char * orig, u_char * chosen);
  25. void EncodeHAM8(pixel * pixrow, pixval maxval, u_char * yham, u_short xsize,
  26.         int do_histogram);
  27.  
  28. static u_short compute_error(u_char * orig, u_char * chosen)
  29. {
  30.   u_short ret, x;
  31.  
  32.   x = abs(orig[0] - chosen[0]);
  33.   ret = Mult_Table[x];
  34.   x = abs(orig[1] - chosen[1]);
  35.   ret += Mult_Table[x];
  36.   x = abs(orig[2] - chosen[2]);
  37.   ret += Mult_Table[x];
  38.  
  39.   return ret;
  40. }
  41.  
  42. void EncodeHAM8(pixel * pixrow, pixval maxval, u_char * yham, u_short xsize,
  43.         int do_histogram)
  44. {
  45.   u_char orig_cols[3], left[3], cache, *finham;
  46.   u_char best_color = 3, colcount = 0, ham_offset, tmp, tmp2, change_val;
  47.   u_long CacheOffset, offset;
  48.   u_short err, min_error;
  49.   pixel p;
  50.  
  51.   memcpy(left, ColorTable, sizeof(left));
  52.  
  53.   for( finham = (yham + xsize - 1); yham <= finham; )
  54.   {
  55.     PPM_DEPTH(p, (*pixrow), maxval, 63);
  56.     pixrow++;
  57.  
  58.     orig_cols[0] = PPM_GETB(p);
  59.     orig_cols[1] = PPM_GETR(p);
  60.     orig_cols[2] = PPM_GETG(p);
  61.  
  62.     if( left[0] != orig_cols[0] || left[1] != orig_cols[1] ||
  63.         left[2] != orig_cols[2] )
  64.     {
  65.       min_error = 65535;
  66.  
  67.       offset = (orig_cols[1] << 12) | (orig_cols[2] << 6) | orig_cols[0];
  68.       cache = ColorCache[offset];
  69.       if (!cache)
  70.       {
  71.     CacheOffset = offset;
  72.     best_color = offset = 0;
  73.  
  74.     do
  75.     {
  76.       err = compute_error(orig_cols, &ColorTable[offset]);
  77.       offset += 3;
  78.  
  79.       if (err < min_error)
  80.       {
  81.         min_error = err;
  82.         best_color = offset;
  83.       }
  84.     }
  85.     while (err > 0 && offset < 192);
  86.  
  87.     if (err)
  88.     {
  89.       ColorCache[CacheOffset] = best_color;
  90.     }
  91.     else
  92.     {
  93.       min_error = compute_error(orig_cols, &ColorTable[offset - 3]);
  94.     }
  95.       }
  96.       else
  97.       {
  98.     if (!do_histogram)
  99.     {
  100.       *(yham++) = ((cache / 3) - 1) << 2;
  101.           memcpy(left, &ColorTable[best_color - 3], sizeof(left));
  102.       continue;
  103.     }
  104.  
  105.     best_color = cache;
  106.     min_error = compute_error(orig_cols, &ColorTable[best_color - 3]);
  107.       }
  108.  
  109.       change_val = orig_cols[0];
  110.       tmp2 = abs(orig_cols[0] - left[0]);
  111.       ham_offset = 0;
  112.  
  113.       tmp = abs(orig_cols[1] - left[1]);
  114.       if (tmp > tmp2)
  115.       {
  116.     change_val = orig_cols[1];
  117.     ham_offset = 1;
  118.     tmp2 = tmp;
  119.       }
  120.  
  121.       tmp = abs(orig_cols[2] - left[2]);
  122.       if (tmp > tmp2)
  123.       {
  124.     change_val = orig_cols[2];
  125.     ham_offset = 2;
  126.       }
  127.  
  128.       tmp = left[ham_offset];
  129.       left[ham_offset] = change_val;
  130.       err = compute_error(orig_cols, left);
  131.  
  132.       if (min_error >= err)
  133.       {
  134.         /* Use HAM */
  135.         *(yham++) = (change_val << 2) | (ham_offset + 1);
  136.       }
  137.       else
  138.       {
  139.         *(yham++) = ((best_color / 3) - 1) << 2;
  140.         memcpy(left, &ColorTable[best_color - 3], sizeof(left));
  141.       }
  142.     }
  143.     else
  144.     {
  145.       ham_offset = colcount;
  146.       colcount = (colcount + 1) % 3;
  147.  
  148.       left[ham_offset] = orig_cols[ham_offset];
  149.       *(yham++) = (orig_cols[ham_offset] << 2) | (ham_offset + 1);
  150.     }
  151.   }
  152.  
  153.   return;
  154. }
  155.